/**
 * 
 */
package robocup.component.worldmodel.particlefilter;

import java.util.Random;

import robocup.component.geometry.Vektor;
import robocup.component.infotypes.BallInfo;

/**
 * @author werwurm
 * 
 */
public class BallRegion {

  private Vektor   origin;

  protected double minDistance;

  protected double maxDistance;

  protected double minDirection;

  private double   directionDelta;

  private final Vektor   helperVektor = new Vektor();

  private final Random   random       = new Random(System.currentTimeMillis());

  /**
   * A region, in which the ball may be located.
   */
  public BallRegion() {

  }

  public void reinitRegionPos(final BallInfo bi,
      final double headAngle,
      final Vektor myPos) {

    this.origin = myPos;

    this.minDistance = Math
        .log(((double) Math.rint(bi.getDistance() / 0.1) - 0.5) * 0.1);
    this.minDistance = Math
        .exp(((double) Math.rint(this.minDistance / 0.1) - 0.5) * 0.1);
    this.maxDistance = Math
        .log(((double) Math.rint(bi.getDistance() / 0.1) + 0.5) * 0.1);
    this.maxDistance = Math
        .exp(((double) Math.rint(this.maxDistance / 0.1) + 0.5) * 0.1);

    this.minDirection = bi.getDirection() + headAngle - 1;
    this.directionDelta = 2.0;
  }

  public Vektor makeRandomInsideRegion(Vektor point) {

    if (point == null) {
      point = new Vektor();
    }

    point
        .setLength(this.minDistance + (this.maxDistance - this.minDistance) * this.random
            .nextDouble());
    point.rotate(-point.getAngle() + this.minDirection + (2 * this.random
        .nextDouble()));
    return point.addToThis(this.origin);
  }

  public void setOrigin(final Vektor origin) {

    this.origin = origin;
  }

  public double insideRegion(final Vektor point) {

    this.helperVektor.x = point.x;
    this.helperVektor.y = point.y;
    this.helperVektor.subFromThis(this.origin);
    this.helperVektor.rotate(-this.minDirection);
    if (this.helperVektor.getAngle() <= this.directionDelta && this.helperVektor
        .getAngle() >= 0 && this.helperVektor.getLength() >= this.minDistance && this.helperVektor
        .getLength() <= this.maxDistance) {
      return 1.0;
    }
    else {
      return -1;
    }
  }

}
